﻿using System.Collections.Generic;
using Engine;
using Engine.Graphics;
using Game;

namespace Mekiasm
{
    public class SingleChestItem : MachineRotateAbleItem
    {
        public static Dictionary<int, RenderTarget2D> RenderCache = new Dictionary<int, RenderTarget2D>();

        public SingleChestItem(string displayName_) : base(displayName_)
        {
        }

        public override void Initilize()
        {
            textureSlots = new int[] { 22 + itemIndex, 17, 17, 17, 18 + itemIndex, 17 };
        }

        public override string GetDisplayName(SubsystemTerrain subsystemTerrain, int value)
        {
            SaveItemSystem.GetBlockData(value, out Common.SaveItem save);
            if (save != null)
            {
                if (save.GetSlotCount(0) > 0)
                {
                    int v = save.GetSlotValue(0);
                    Block block = BlocksManager.Blocks[Terrain.ExtractContents(v)];
                    return base.GetDisplayName(subsystemTerrain, value) + "<" + block.GetDisplayName(null, v) + ">";
                }
                else
                {
                    return base.GetDisplayName(subsystemTerrain, value) + "<无>";
                }
            }
            else return base.GetDisplayName(subsystemTerrain, value);
        }
        public override MekBlock.DeviceType GetDeviceType()
        {
            return MekBlock.DeviceType.Item;
        }

        DrawBlockEnvironmentData environmentData1 = new DrawBlockEnvironmentData();

        PrimitivesRenderer3D primitives3D = new PrimitivesRenderer3D();

        PrimitivesRenderer2D primitives2D = new PrimitivesRenderer2D();

        public static Matrix CreateScaleTranslation(float sx, float sy, float tx, float ty)
        {
            return new Matrix(sx, 0f, 0f, 0f, 0f, sy, 0f, 0f, 0f, 0f, 1f, 0f, tx, ty, 0f, 1f);
        }


        public override void DrawBlock(PrimitivesRenderer3D primitivesRenderer, int value, Color color, float size, ref Matrix matrix, DrawBlockEnvironmentData environmentData)
        {
            value = ILibrary.setDirection(value, 0);
            ILibrary.DrawCubeBlock(primitivesRenderer, value, new Vector3(size), ref matrix, color, color, environmentData);
            SaveItemSystem.GetBlockData(value, out var item);
            if (item != null && item.GetSlotCount(0) > 0)
            {
                if (!RenderCache.TryGetValue(value, out var renderTarget2D))
                {
                    renderTarget2D = new RenderTarget2D(256, 256, 1, ColorFormat.Rgba8888, DepthFormat.None);
                    RenderCache.Add(value, renderTarget2D);
                }

                MekModLoader.Dispatch(delegate {
                    RenderTarget2D target2D = Display.RenderTarget;
                    Display.RenderTarget = renderTarget2D;
                    Display.Clear(Color.Transparent);
                    var slot = item.Slots[0];
                    var block = BlocksManager.Blocks[Terrain.ExtractContents(slot.Value)];
                    Matrix matrix1 = Matrix.Identity;
                    Matrix m2 = Matrix.CreateLookAt(block.GetIconViewOffset(slot.Value, environmentData1), Vector3.Zero, Vector3.UnitY);
                    m2 *= Matrix.CreateOrthographic(3.6f, 3.6f, -10f, 10f);
                    m2 *= Matrix.CreateTranslation(0f, 0.2f, 0f);
                    environmentData1.ViewProjectionMatrix = m2;
                    environmentData1.Light = 15;
                    block.DrawBlock(primitives3D, slot.Value, color, 0.8f, ref matrix1, environmentData1);
                    FontBatch2D fontBatch = primitives2D.FontBatch(LabelWidget.BitmapFont, 1, DepthStencilState.None, null, BlendState.Opaque, SamplerState.PointClamp);
                    fontBatch.QueueText($"{slot.Count}", new Vector2(128, 180), 0f, Color.White, TextAnchor.HorizontalCenter, new Vector2(2), Vector2.Zero);//不是纹理坐标				
                    primitives2D.Flush();
                    primitives3D.Flush(matrix1);
                    Display.RenderTarget = target2D;
                });
                ILibrary.DrawCubeBlockFace(primitivesRenderer, value, new Vector3(size), ref matrix, color, environmentData, renderTarget2D);
            }
        }
        public override bool IsInteractive(SubsystemTerrain subsystemTerrain, int value)
        {
            return true;
        }
        public override int GetMaxStacking()
        {
            return 1024 * (int)MathUtils.Pow(2, itemIndex);
        }
        public override bool OnInteract(SubsystemBlockBehavior blockBehavior, TerrainRaycastResult raycastResult, ComponentMiner componentMiner)
        {
            SaveItemSystem.GetBlockData(raycastResult.Value, out Common.SaveItem toolSaveItem);
            if (toolSaveItem != null)
            {
                Point3 point = raycastResult.CellFace.Point;
                for (int x = point.X - 1; x <= point.X + 1; x++)
                {
                    for (int y = point.Y - 1; y <= point.Y + 1; y++)
                    {
                        for (int z = point.Z - 1; z <= point.Z + 1; z++)
                        {
                            if (x == point.X && y == point.Y && z == point.Z) continue;
                            if (ILibrary.SubsystemTerrain.Terrain.GetCellContents(x, y, z) == 0)
                            {
                                toolSaveItem.DropItems(new Vector3(x, y, z), 0, 1);
                                return true;
                            }
                        }
                    }
                }
            }
            return true;
        }
        public override void GetDropValues(SubsystemTerrain subsystemTerrain, int oldValue, int newValue, int toolLevel, List<BlockDropValue> dropValues, out bool showDebris)
        {
            SaveItemSystem.GetBlockData(oldValue, out Common.SaveItem toolSaveItem);
            bool isEmpty = true;
            int value = oldValue;
            if (toolSaveItem != null)
            {
                for (int i = 0; i < toolSaveItem.SlotsCount; i++)
                {
                    if (toolSaveItem.GetSlotCount(i) > 0)
                    {
                        isEmpty = false;
                        break;
                    }
                }
                if (isEmpty)//为空值，还原为初始值
                {
                    SaveItemSystem.RemoveBlockData(oldValue, toolSaveItem);
                    value = ILibrary.GetBasicValue(oldValue);
                }
            }
            else
            {//没有saveItem，还原为初始值
                value = ILibrary.GetBasicValue(oldValue);
            }
            showDebris = true;
            dropValues.Add(new BlockDropValue() { Value = value, Count = 1 });
        }
        public override void OnHitByProjectile(CellFace cellFace, WorldItem worldItem)
        {
            int Dropvalue = worldItem.Value;
            Pickable pickable = worldItem as Pickable;
            int count = (pickable == null ? 0 : pickable.Count);
            int x = cellFace.X; int y = cellFace.Y; int z = cellFace.Z;
            int value = ILibrary.SubsystemTerrain.Terrain.GetCellValueFast(x, y, z);
            SaveItemSystem.GetBlockData(value, out Common.SaveItem toolSaveItem);
            if (toolSaveItem == null)
            {
                int newValue2 = SaveItemSystem.StoreBlockData(value, 0, 0, 1);
                ILibrary.SubsystemTerrain.ChangeCell(x, y, z, newValue2);
                SaveItemSystem.GetBlockData(newValue2, out Common.SaveItem toolSaveItem2);
                toolSaveItem = toolSaveItem2;
            }
            if ((toolSaveItem.GetSlotCount(0) == 0) || (toolSaveItem.GetSlotCount(0) + count <= GetMaxStacking() && toolSaveItem.GetSlotValue(0) == Dropvalue))
            {
                toolSaveItem.AddSlotItems(0, Dropvalue, count);
                worldItem.ToRemove = true;
                ILibrary.SubsystemAudio.PlaySound("Audio/PickableCollected", 1f, 0f, worldItem.Position, 3f, autoDelay: true);
            }
        }
        public override void OnBlockGenerated(int value, int x, int y, int z, bool isLoaded)
        {
            SubsystemSingleChestDraw.Add(x, y, z);
        }
        public override void OnBlockAdded(SubsystemBlockBehavior blockBehavior, int value, int oldValue, int x, int y, int z)
        {
            SubsystemSingleChestDraw.Add(x, y, z);
        }
        public override void OnBlockRemoved(SubsystemBlockBehavior blockBehavior, int value, int newValue, int x, int y, int z)
        {

            SubsystemSingleChestDraw.Remove(x, y, z, value);
        }
    }
}
